package cn.gson.financial.controller;

import cn.gson.financial.annotation.IgnoresLogin;
import cn.gson.financial.base.BaseCrudController;
import cn.gson.financial.kernel.common.DoubleValueUtil;
import cn.gson.financial.kernel.controller.JsonResult;
import cn.gson.financial.kernel.model.entity.Subject;
import cn.gson.financial.kernel.model.entity.VoucherDetails;
import cn.gson.financial.kernel.model.vo.CategoryVo;
import cn.gson.financial.kernel.model.vo.DelAuxiliaryVo;
import cn.gson.financial.kernel.model.vo.InitBlanceVo;
import cn.gson.financial.kernel.model.vo.InitialBalanceVo;
import cn.gson.financial.kernel.service.SubjectService;
import cn.gson.financial.kernel.service.VoucherDetailsService;
import cn.gson.financial.kernel.utils.BaseUtil;
import cn.gson.financial.kernel.utils.JsonStringUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 期初
 */
@RestController
@RequestMapping("/initial-balance")
@AllArgsConstructor
@Slf4j
public class InitialBalanceController extends BaseCrudController<VoucherDetailsService, VoucherDetails> {

    private SubjectService subjectService;

    @Autowired
    private VoucherDetailsService voucherDetailsService;

    @Override
    public JsonResult list(@RequestParam Map<String, String> params) {

        List<VoucherDetails> balanceList = this.service.balanceList(this.accountSetsId, params.get("type"),Integer.parseInt(params.get("currencyId")));

        List<VoucherDetails> auxiliaryList = this.service.auxiliaryList(this.accountSetsId, params.get("type"),Integer.parseInt(params.get("currencyId")));
        auxiliaryList.forEach(System.out::println);

        Map<String, VoucherDetails> detailsMap = balanceList.stream().collect(Collectors.toMap(v -> v.getSubjectId() + v.getSubjectCode(), voucherDetails -> voucherDetails));

        List<Subject> subjectList = subjectService.findByTypeCurrency(this.accountSetsId,params.get("type"),Integer.parseInt(params.get("currencyId")));
        List<Integer> leafs = subjectService.leafList(this.accountSetsId);
        List<InitialBalanceVo> result = subjectList.stream().collect(ArrayList::new, (list, subject) -> {
            VoucherDetails details = detailsMap.get(subject.getId() + subject.getCode());
            InitialBalanceVo vo = new InitialBalanceVo();

            setData(vo, details);
            vo.setSubjectId(subject.getId());
            vo.setType(subject.getType());
            vo.setCode(subject.getCode());
            vo.setName(subject.getName());
            vo.setMnemonicCode(subject.getMnemonicCode());
            vo.setBalanceDirection(subject.getBalanceDirection());
            vo.setStatus(subject.getStatus());
            vo.setParentId(subject.getParentId());
            vo.setLevel(subject.getLevel());
            vo.setSystemDefault(subject.getSystemDefault());
            vo.setAccountSetsId(subject.getAccountSetsId());
            vo.setUnit(subject.getUnit());
            vo.setAuxiliaryAccounting(subject.getAuxiliaryAccounting());
            vo.setLeaf(leafs.contains(subject.getId()));
            vo.setCurrencyAccounting(subject.getCurrencyAccounting());
            vo.setYnDel(false);

            list.add(vo);
        }, List::addAll);

        auxiliaryList.forEach(voucherDetails -> {
            InitialBalanceVo vo = new InitialBalanceVo();
            Subject subject = voucherDetails.getSubject();
            VoucherDetails details = detailsMap.get(subject.getId() + voucherDetails.getSubjectCode());
            setData(vo, details);
            vo.setSubjectId(voucherDetails.getSubjectId());
            vo.setCode(voucherDetails.getSubjectCode());
            vo.setName(subject.getName() + voucherDetails.getAuxiliaryTitle());
            vo.setBalanceDirection(subject.getBalanceDirection());
            vo.setParentId(subject.getParentId());
            vo.setLevel((short) (subject.getLevel() + 1));
            vo.setSystemDefault(subject.getSystemDefault());
            vo.setAccountSetsId(subject.getAccountSetsId());
            vo.setUnit(subject.getUnit());
            vo.setLeaf(true);
            vo.setYnDel(true);
            vo.setCurrencyAccounting(subject.getCurrencyAccounting());
            result.add(vo);
        });
        List<InitialBalanceVo> collect = result.stream().sorted(Comparator.comparing(Subject::getCode)).collect(Collectors.toList());
        return JsonResult.successful(this.summaryQiChu(collect));
    }

    //汇总期初
    private List<InitialBalanceVo> summaryQiChu(List<InitialBalanceVo> collect){
        for (int i = collect.size() - 1; i >= 0; i--) {
            Double num = 0.0;
            Double beginBalance = 0.0;
            Double cumulativeDebitNum = 0.0;
            Double cumulativeDebit = 0.0;
            Double cumulativeCreditNum = 0.0;
            Double cumulativeCredit = 0.0;

            Double currencyDebit = 0.0;//原币期初余额
            Double currencyCumulativeDebit = 0.0;
            Double currencyCumulativeCredit = 0.0;
            Integer subjectId = collect.get(i).getSubjectId();
            if (collect.get(i).isYnDel()){
                continue;
            }
            //如果是叶子节点并且辅助核算不为空，即页面上带有+的数据
            if (collect.get(i).isLeaf() == true && !(collect.get(i).getAuxiliaryAccounting() == null || collect.get(i).getAuxiliaryAccounting().equals(""))){
                for (InitialBalanceVo balanceVo : collect) {
                    if (subjectId.equals(balanceVo.getSubjectId())){
                        num += (balanceVo.getNum()==null?0.0:balanceVo.getNum());//期初余额数量
                        cumulativeDebitNum += (balanceVo.getCumulativeDebitNum()==null?0.0:balanceVo.getCumulativeDebitNum());//借方累计数量
                        cumulativeCreditNum += (balanceVo.getCumulativeCreditNum()==null?0.0:balanceVo.getCumulativeCreditNum());//贷方累计数量

                        cumulativeDebit += (balanceVo.getCumulativeDebit()==null?0.0:balanceVo.getCumulativeDebit());//借方累计金额
                        cumulativeCredit += (balanceVo.getCumulativeCredit()==null?0.0:balanceVo.getCumulativeCredit());//贷方累计金额
                        currencyCumulativeDebit += (balanceVo.getCurrencyCumulativeDebit()==null?0.0:balanceVo.getCurrencyCumulativeDebit());//外币累计借方
                        currencyCumulativeCredit += (balanceVo.getCurrencyCumulativeCredit()==null?0.0:balanceVo.getCurrencyCumulativeCredit());//外币累计贷方
                        currencyCumulativeCredit += (balanceVo.getCurrencyCumulativeCredit()==null?0.0:balanceVo.getCurrencyCumulativeCredit());//外币累计贷方

                        if (balanceVo.getBalanceDirection().equals(collect.get(i).getBalanceDirection())){
                            beginBalance += (balanceVo.getBeginBalance()==null?0.0:balanceVo.getBeginBalance());//期初余额金额
                            currencyDebit += (balanceVo.getCurrencyDebit()==null?0.0:balanceVo.getCurrencyDebit());//期初外币
                        }else {
                            beginBalance -= (balanceVo.getBeginBalance()==null?0.0:balanceVo.getBeginBalance());//期初余额金额
                            currencyDebit -= (balanceVo.getCurrencyDebit()==null?0.0:balanceVo.getCurrencyDebit());//期初外币
                        }
                    }
                }
            }else {
                for (InitialBalanceVo balanceVo : collect) {
                    Integer parentId = balanceVo.getParentId();
                    if (subjectId.equals(parentId) && !(balanceVo.isLeaf() == true && !(balanceVo.getAuxiliaryAccounting() == null || balanceVo.getAuxiliaryAccounting().equals("")))){
                        num += (balanceVo.getNum()==null?0.0:balanceVo.getNum());//期初余额数量
                        cumulativeDebitNum += (balanceVo.getCumulativeDebitNum()==null?0.0:balanceVo.getCumulativeDebitNum());//借方累计数量
                        cumulativeCreditNum += (balanceVo.getCumulativeCreditNum()==null?0.0:balanceVo.getCumulativeCreditNum());//贷方累计数量

                        cumulativeDebit += (balanceVo.getCumulativeDebit()==null?0.0:balanceVo.getCumulativeDebit());//借方累计金额
                        cumulativeCredit += (balanceVo.getCumulativeCredit()==null?0.0:balanceVo.getCumulativeCredit());//贷方累计金额
                        currencyCumulativeDebit += (balanceVo.getCurrencyCumulativeDebit()==null?0.0:balanceVo.getCurrencyCumulativeDebit());//外币累计借方
                        currencyCumulativeCredit += (balanceVo.getCurrencyCumulativeCredit()==null?0.0:balanceVo.getCurrencyCumulativeCredit());//外币累计贷方

                        if (balanceVo.getBalanceDirection().equals(collect.get(i).getBalanceDirection())){
                           beginBalance += (balanceVo.getBeginBalance()==null?0.0:balanceVo.getBeginBalance());//期初余额金额
                           currencyDebit += (balanceVo.getCurrencyDebit()==null?0.0:balanceVo.getCurrencyDebit());//期初外币
                       }else {
                           beginBalance -= (balanceVo.getBeginBalance()==null?0.0:balanceVo.getBeginBalance());//期初余额金额
                           currencyDebit -= (balanceVo.getCurrencyDebit()==null?0.0:balanceVo.getCurrencyDebit());//期初外币
                       }
                    }
                }
            }
            collect.get(i).setNum(num==0.0?collect.get(i).getNum():num);//期初余额数量
            collect.get(i).setBeginBalance(beginBalance==0.0? BaseUtil.checkDoubleIsNull(collect.get(i).getBeginBalance()):beginBalance);//期初余额金额
            collect.get(i).setCurrencyDebit(currencyDebit==0.0? BaseUtil.checkDoubleIsNull(collect.get(i).getCurrencyDebit()):currencyDebit);//期初外币
            collect.get(i).setCumulativeDebitNum(cumulativeDebitNum==0.0?collect.get(i).getCumulativeDebitNum():cumulativeDebitNum);//借方累计数量
            collect.get(i).setCumulativeDebit(cumulativeDebit==0.0?collect.get(i).getCumulativeDebit():cumulativeDebit);//借方累计金额
            collect.get(i).setCumulativeCreditNum(cumulativeCreditNum==0.0?collect.get(i).getCumulativeCreditNum():cumulativeCreditNum);//贷方累计数量
            collect.get(i).setCumulativeCredit(cumulativeCredit==0.0?collect.get(i).getCumulativeCredit():cumulativeCredit);//贷方累计金额
            //外币汇总
            collect.get(i).setCurrencyCumulativeDebit(currencyCumulativeDebit==0.0?collect.get(i).getCurrencyCumulativeDebit():currencyCumulativeDebit);//外币累计借方
            collect.get(i).setCurrencyCumulativeCredit(currencyCumulativeCredit==0.0?collect.get(i).getCurrencyCumulativeCredit():currencyCumulativeCredit);//外币累计贷方
        }
        return collect;
    }


    /**
     * 初始化 期初 余额 数量
     * @param vo
     * @param blanceVo
     */
    private void setInitialBalanceVo(InitialBalanceVo vo, InitBlanceVo blanceVo){
        if (blanceVo != null) {
            vo.setBeginBalance(DoubleValueUtil.getNotNullVal(blanceVo.getBeginBalance()));
            vo.setNum(blanceVo.getBeginBalanceNum());
            vo.setCumulativeCredit(blanceVo.getCumulativeCredit());
            vo.setCumulativeDebit(blanceVo.getCumulativeDebit());
            vo.setCumulativeCreditNum(blanceVo.getCumulativeCreditNum());
            vo.setCumulativeDebitNum(blanceVo.getCumulativeDebitNum());
        }
    }

    //修改期初数量金额的接口
    @IgnoresLogin
    @PostMapping("/sInitBl")
    public JsonResult save(@RequestBody InitBlanceVo vo){
        vo.setAccountSetsId(this.accountSetsId);
        InitBlanceVo initBlanceVo = subjectService.findBySubIdAndAccountSwtId(vo.getSubjectId(), this.accountSetsId);

        if(initBlanceVo == null){
            boolean f =  subjectService.saveInitBlanceVo(vo);
            if(f){
                return JsonResult.successful("保存成功");
            }
            return JsonResult.failure("保存失败");
        }else {
            boolean f =  subjectService.updateInitBlanceVo(vo);
            if(f){
                return JsonResult.successful("保存成功");
            }
            return JsonResult.failure("保存失败");
        }
    }

    private void setData(InitialBalanceVo vo, VoucherDetails details) {
        if (details != null) {
            vo.setBeginBalance(DoubleValueUtil.getNotNullVal(details.getDebitAmount(), details.getCreditAmount()));
            vo.setNum(details.getNum());
            vo.setCumulativeCredit(details.getCumulativeCredit());
            vo.setCumulativeDebit(details.getCumulativeDebit());
            vo.setCumulativeCreditNum(details.getCumulativeCreditNum());
            vo.setCumulativeDebitNum(details.getCumulativeDebitNum());

            vo.setCurrencyCredit(details.getCurrencyCredit());
            vo.setCurrencyDebit(details.getCurrencyDebit());
            vo.setCurrencyCumulativeDebit(details.getCurrencyCumulativeDebit());
            vo.setCurrencyCumulativeCredit(details.getCurrencyCumulativeCredit());
        }
    }

    @Override
    public JsonResult save(@RequestBody VoucherDetails entity) {
        log.info("入参：" + entity);
        Subject subject = subjectService.getById(entity.getSubjectId());
        String currencyAccounting = subject.getCurrencyAccounting();
        if (currencyAccounting == null || currencyAccounting.equals("")){
            //该科目没有设置外币核算
        }else {
            String currencyId = JsonStringUtil.JsonStringGetValueByKey(currencyAccounting, "id");
            if (currencyId == null || currencyId.equals("")){
                //不需要做明细做外币插入
            }else {
                System.out.println(currencyAccounting);
                entity.setCurrencyId(Integer.parseInt(currencyId));
                entity.setCurrencyName(JsonStringUtil.JsonStringGetValueByKey(currencyAccounting,"name"));
                String exchangeRate = JsonStringUtil.JsonStringGetValueByKey(currencyAccounting, "exchange_rate");
                entity.setExchangeRate(((exchangeRate ==null) || (exchangeRate.equals("") )? 0:Double.parseDouble(exchangeRate)));
            }
        }

        JsonResult result = super.save(entity);
        result.setData(entity);

        //如果设置的期初数据全为null或者为0，就删除该期初
        voucherDetailsService.delQIChu(this.accountSetsId,subject.getId(),subject.getCode());
        return result;
    }


    @PostMapping("auxiliary")
    public JsonResult auxiliary(@RequestBody HashMap<String, Object> entity) {
        //查询该科目有没有该期初，如果有的话就不进行新增操作
        Object auxiliary = entity.get("auxiliary");
        if (auxiliary != null){
            List<CategoryVo> categoryVoList = new ArrayList<>();

            JSONObject jsonObj = (JSONObject.parseObject(JSONObject.toJSONString(auxiliary)));
            Map<String, Object> map = jsonObj.getInnerMap();
            map.forEach((key, value) -> {
                CategoryVo categoryVo = new CategoryVo();
                categoryVo.setCategoryId(Integer.parseInt(key));
                categoryVo.setCategoryDetailsId((Integer) value);
                categoryVoList.add(categoryVo);
                System.out.println(key+"--->" + value);
            });
            Boolean isInsert = service.checkIsInsertQiChu(this.accountSetsId,(Integer) entity.get("subjectId"),categoryVoList);
            if (!isInsert){
                return JsonResult.failure("该辅助核算已经存在！");
            }
        }
        this.service.saveAuxiliary(this.accountSetsId, entity);
        return JsonResult.successful("新增成功");
    }

    /**
     * 初期测试平衡
     * @return
     */
    @IgnoresLogin
    @GetMapping("trialBalance")
    public JsonResult trialBalance() {
        Map<String, Map<String, Double>> data = this.service.trialBalance(this.accountSetsId);
        return JsonResult.successful(data);
    }

    @PostMapping("delAuxiliary")
    @IgnoresLogin
    public JsonResult delAuxiliary(@RequestBody DelAuxiliaryVo vo) {
       boolean flag = this.service.removeAuxiliary(vo.getSubjectId(),vo.getName());
       if(flag){
           return JsonResult.successful("删除成功!");
       }
       return JsonResult.failure("该科目可能已做账,请检查!");
    }
}
